#include <iostream>
#include <cstdlib>

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>

#include "string.h" // memset
#include "Client.hh"
#include "constants/network.h"
//#include "common/NetworkDevice.hh"

// NOTE: BSD style...
// cd do it in vanilla C

Client::Client(char* host, char* port, int msgCount, char** msgList)
  : _host(host),
    _port(port),
    _msgCount(msgCount),
    _msgList(msgList)
{
#ifdef DEBUG
  printf("printing datas\n");
  for (int i = 0; _msgList[i]; ++i)
  {
	for (int j = 0; _msgList[i][j]; ++j)
	  printf("%c", _msgList[i][j]);
	printf("\n");
  }
  printf("\n");
#endif

  buildHints();
  init();
  run();
}

Client::~Client()
{
}

void Client::buildHints()
{
  /* Obtain address(es) matching host/port */

  memset(&_hints, 0, sizeof(struct addrinfo));
  _hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
  _hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
  _hints.ai_flags = 0;
  _hints.ai_protocol = 0;          /* Any protocol */
}


void Client::init()
{
  // err
  //if ((_s = getaddrinfo(_host, _port, &_hints, &_result)))
  if ((_s = getaddrinfo("localhost", "12345", &_hints, &_result)))
  {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(_s));
    exit(EXIT_FAILURE);
  }

  /* getaddrinfo() returns a list of address structures.
     Try each address until we successfully connect(2).
     If socket(2) (or connect(2)) fails, we (close the socket
     and) try the next address. */

  for (_rp = _result; _rp != NULL; _rp = _rp->ai_next)
  {
    printf("trying\n"); //

    if ((_sfd = socket(_rp->ai_family, _rp->ai_socktype, _rp->ai_protocol)) == -1)
      continue;

    if (connect(_sfd, _rp->ai_addr, _rp->ai_addrlen) != -1)
    {
      printf("connect\n");
      // print sfd
      printf("_____\nSFD:\n...");
      break; /* Success */
    }

    close(_sfd);
  }

  if (!_rp) /* No address succeeded */
  {
    fprintf(stderr, "Unable to connect");
    exit(EXIT_FAILURE);
  }

  freeaddrinfo(_result);  /* No longer needed */

  printf("init done\n");

  /* Send remaining command-line arguments as separate
     datagrams, and read responses from server */
}



// "Usage: %s host port msg...\n"
//int main(int argc, char *argv[])

void Client::run()
{
  for (int i = 0; i < _msgCount; ++i)
  {
    ssize_t len = strlen(_msgList[i]) + 1;
    /* +1 for terminating null byte */

    printf("msg: %s\n", _msgList[i]);
    printf("sfd: %i\n", _sfd);

    if (len + 1 > SERVER_BUF_SIZE)
    {
	  std::cerr << "message size overflow" << i << std::endl;
	  std::cerr << "Message size was: " << len << std::endl;
      continue;
    }

    // we' ll need to build msg list
    if (write(_sfd, _msgList[i], len) != len)
    {
	  std::cerr << "partial/failed write" << std::endl;
      exit(EXIT_FAILURE);
    }

    if ((_nread = read(_sfd, _buf, SERVER_BUF_SIZE)) == -1)
    {
      perror("read"); // 'connection refused'
      exit(EXIT_FAILURE);
    }

    printf("Received %ld bytes: %s\n", (long) _nread, _buf);
  }

  exit(EXIT_SUCCESS);
}
